package com.rw.map.websocket;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.PostConstruct;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.rw.map.model.CameraDataDTO;
import com.rw.map.model.NavigateVO;
import com.rw.map.model.Result;
import com.rw.map.model.TrailDetailIncQueryDTO;
import com.rw.map.service.NavigateFeignClient;
import com.rw.map.service.NavigateService;
import com.rw.map.utils.DateUtils;
import com.rw.map.utils.RedisUtil;
import com.rw.map.utils.RestTemplateUtils;
import com.rw.map.utils.StringUtils;

/**
 * 
 * @author forest
 *
 */
@ServerEndpoint(value = "/ws/asset/{floorId}/{uid}/{buildingId}")
@Component
public class WebSocketServer {

	private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);

	private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	@Autowired
	private NavigateFeignClient feignClient;

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private NavigateService navigateService;

	@Autowired
	private RestTemplateUtils restTemplateUtils;
	
	@PostConstruct
	public void init() {
		log.info("websocket 加载");
	}

	private static final AtomicInteger OnlineCount = new AtomicInteger(0);

	// concurrent包的线程安全Set，用来存放每个客户端对应的Session对象。
	private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();

	/**
	 * 连接建立成功调用的方法
	 */
	@OnOpen
	public void onOpen(Session session) {
		SessionSet.add(session);
		int cnt = OnlineCount.incrementAndGet(); // 在线数加1
		log.info("有连接加入，当前连接数为：{}", cnt);
		//sendMessage(session, "连接成功");
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(Session session) {
		SessionSet.remove(session);
		int cnt = OnlineCount.decrementAndGet();
		log.info("有连接关闭，当前连接数为：{}", cnt);
	}

	/**
	 * 收到客户端消息后调用的方法
	 *
	 * @param message 客户端发送过来的消息
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		log.info("来自客户端的消息：{}", message);
		sendMessage(session, "收到消息，消息内容：" + message);

	}

	/**
	 * 出现错误
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		log.error("发生错误：{}，Session ID： {}", error.getMessage(), session.getId(), error);
	}

	/**
	 * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
	 * 
	 * @param session
	 * @param message
	 */
	public void sendMessage(Session session, String message) {
		try {
			session.getBasicRemote()
					.sendText(message);
		} catch (IOException e) {
			log.error("发送消息出错：{}", e.getMessage(), e);
		}
	}

	/**
	 * 群发消息
	 * 
	 * @param message
	 * @throws IOException
	 */
	public void broadCastNavigateInfo() throws IOException {
		// 给连接进来的每个session推送数据
		for (Session session : SessionSet) {
			if (session.isOpen()) {
				log.info("开始执行推送任务。。。。。。。");
				Map<String, String> map = session.getPathParameters();
				String floorId = map.get("floorId");
				String uid = map.get("uid");
				String buildingId = map.get("buildingId");
				try {
					Map<String, Object> m = (Map<String, Object>) redisUtil.get(buildingId + floorId + uid);
					if (m != null) {
						TrailDetailIncQueryDTO queryDTO = new TrailDetailIncQueryDTO();
						queryDTO.setLastTime(DateUtils.localDateTimePares(m.get("lastTime").toString()));
						queryDTO.setLastDataId(Long.valueOf(m.get("lastDataId").toString()));
						queryDTO.setNodeCode(floorId);
						queryDTO.setMarkNodes(navigateService.getNaviPathCamera(floorId));
						//String result = feignClient.getTrailDetailInc(queryDTO);
						String result = restTemplateUtils.httpRequestByTrailDetailInc(queryDTO, "http://58.251.16.82:7000/trail/detail/inc", m.get("lastTime").toString());
						log.info("socket<>detail/inc result=======>{}", result);
						if(StringUtils.isNotBlank(result)) {
							CameraDataDTO cd = navigateService.computeCameraData(result, buildingId);
							if(cd != null) {
								List<NavigateVO> navigateList = navigateService.getNavigateData(cd);
								// 更新缓存
								m.put("lastDataId", cd.getLastDataId());
								m.put("lastTime", DateUtils.formatDateTime(cd.getLastTime()));
								redisUtil.set(buildingId + cd.getNodeCode() + uid, m);
								sendMessage(session, JSON.toJSONString(Result.success(navigateList)));
							}
						}
					}

				} catch (Exception e) {
					log.error("推送任务执行异常：{}", e.getMessage(), e);
				}

			}
		}
	}

	

	/**
	 * 指定Session发送消息
	 * 
	 * @param sessionId
	 * @param message
	 * @throws IOException
	 */
	public void sendMessage(String message, String sessionId) throws IOException {
		Session session = null;
		for (Session s : SessionSet) {
			if (s.getId().equals(sessionId)) {
				session = s;
				break;
			}
		}
		if (session != null) {
			sendMessage(session, message);
		} else {
			log.warn("没有找到你指定ID的会话：{}", sessionId);
		}
	}

	public static void main(String[] args) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime time = LocalDateTime.now();
		String localTime = df.format(time);
		LocalDateTime ldt = LocalDateTime.parse("2018-01-12 17:07:05", df);
		System.out.println("LocalDateTime转成String类型的时间：" + localTime);
		System.out.println("String类型的时间转成LocalDateTime：" + ldt);
	}

}
